import org.springframework.beans.factory.InitializingBean
import resolver.DatabaseContentResolver
import resolver.OscarResolver
import resolver.Resolveable
import resolver.SingleLineRegExpressionResolver
import types.Hit
import resolver.interceptor.StoplistInterceptor

/**
 * service which discovers compounds in text
 */
class DiscoveryService implements InitializingBean {

  boolean transactional = true
  def grailsApplication
  def setting

  LookupService lookupService

  void afterPropertiesSet() {
    this.setting = grailsApplication.config.setting


    //register interceptor, should be done over grails config no idea how
    resolver.each {Resolveable resolver ->
      if (resolver != null) {
        resolver.addInterceptor((new StoplistInterceptor()))
      }
      else {
        log.warn "current resolver is null!"
      }
    }
  }

  /**
   * contains all our registered resolver
   */
  private static def resolver =
  [
          //TODO should be done over grails config system, no idea how...

          //uses oscar for chemicla lookup
          //  new OscarResolver(0.5),

          //queryClass lookup against the database
          DatabaseContentResolver.getInstance(),

          //find combouds based on expressions
          new SingleLineRegExpressionResolver()

  ]

  /**
   * does the actual discovery
   */
  Collection<Map<Compound, ?>> process(String query, limitConfidence) {
    Collection<Map<Compound, ?>> result = new Vector<Map<Compound, ?>>()
    for (Hit hit: resolveContent(query, resolver, limitConfidence)) {
      Collection<Compound> lookedup = lookupService.lookupByHit(hit)
      for (Compound compound: lookedup) {
        result.add([compound: compound, result: compound.dbLinks, hit: hit.value, resolver: hit.getOrigin().canonicalName])
      }
    }
    log.debug("return: ${result}")
    //return our result
    return result

  }

  /**
   * discovers all hits for the given query
   */
  public Set<Hit> resolveContent(String query, List resolver, limitConfidence) {
    Set<Hit> result = new HashSet<Hit>()

    log.debug "confidence level was set to ${limitConfidence}"


    log.debug "executing query: ${query}"
    //we are using the resolver to find compounds
    resolver.each {Resolveable resolveable ->
      //log.debug("calling: ${resolveable.class.name}")
      try {
        resolveable.activateResolver()
        resolveable.setConfidenceLevel limitConfidence

        def temp = resolveable.resolve(query)
       // log.debug("found: ${temp}")

        result.addAll(temp)
        resolveable.disactivateResolver()
      }
      catch (Exception e) {
        log.error(e.getMessage(), e
        )
      }
    }
    return result
  }

}
